//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<file_op.h>
///	@path	~/src/lib/system/
///	@date	2007/11/22
///	@desc	Os's file Op encapsulation.

#pragma once

#include "xeres.h"

#include <vector>

#include "lib/system/signal.h"
#include "lib/utilities/time.h"
#include "lib/utilities/callback.h"

namespace xeres {

	/*! 
		\enum	FILE_STATUS
		\brief	FileOp status.
	*/
	enum FILE_STATUS
	{
		/// \brief Indicates file is ready, or current operation is ok.
		FILE_READY = 0 ,
		/// \brief File comes to EOF.
		FILE_EOF ,
		/// \brief Indicates another operation is using file.
		FILE_WORKING ,
		/// \brief General IO error.
		FILE_ERROR  ,
		/// \brief Indicate file does not exist.
		FILE_NOFILE ,
		/// \brief Indicate file existed.
		FILE_EXISTED ,
		/// \brief Indicate destination file is directory
		FILE_DIR ,
		// \brief Indicate FileOp has opened another file and is not closed yet.
		FILE_OPENED ,
		FILE_STATUS_last 
	};

	/*!
		\class	FileOp
		\brief	Os's file Op encapsulation.
		\details
			Like most library, we encapsulates most file operation in a simple class.<BR>
			FileOp provide most common file operations, which are not recommended to use
			directly while programming game engine. This class is used by low level functions.<BR>
			When demanding access to data, we strongly recommend functions in database module.

		\sa	IFile
	*/
	class FileOp
	{
	public:

		/// \name Constructor & Destructor
		//@{

		/// \ctor
		FileOp( void );

		/// \dtor
		~FileOp( void );

		//@}

		/// \name File Operations
		//@{

		/*!
			\brief		Open file for read.
		*/
		FILE_STATUS OpenFile( const WString& path , bool shared = false );

		/*!
			\brief		Create file for write.
		*/
		FILE_STATUS CreateFile( const WString& path , bool create_always = false , bool append = false );

		/*!
			\brief		Open directory as special file.
		*/
		FILE_STATUS OpenDir( const WString& path );

		/*!
			\brief		Close current file.
		*/
		FILE_STATUS Close( void );

		/*!
			\brief		Test if file op opened a file.
		*/
		bool IsOpened( void ) const { return m_hFile != NULL; }

		/*!
			\brief		Get file current status.
		*/
		FILE_STATUS Status( void ) const;

		/*!
			\brief		Read data from file.
		*/
		FILE_STATUS Read( void * buffer , size_t len , size_t * readsize );

		/*!
			\brief		Write data to file.
		*/
		FILE_STATUS Write( const void * buffer , size_t len , size_t * writesize );

		/*!
			\brief		Seek to file pos.
		*/
		bool Seek( int64 pos , bool abs_seek );

		/*!
			\brief		Seek to end of file.
		*/
		bool SeekEof( void );

		/*!
			\brief		Get current file pos.
		*/
		uint64 Tell( void );

		/*!
			\brief		Get file size.
		*/
		uint64 Size( void );

		/*!
			\brief		Get file time info.
		*/
		bool GetFileTime( DateTime& creation , DateTime& accessed , DateTime& modification );

		/*!
			\brief		Get file path.
		*/
		const WString& GetFilePath( void ) const { return m_path; }

		//@}

		/// \name File & Directory Manipulation
		//@{

		/*!
			\brief		Test if file exists.
		*/
		static FILE_STATUS FileExist( const WString& path );

		/*!
			\brief		Copy specific file.
		*/
		static FILE_STATUS CopyFile( const WString& src , const WString& dst , bool overwrite = false );

		/*!
			\brief		Delete specific file.
		*/
		static FILE_STATUS DeleteFile( const WString& path );

		/*!
			\brief		List directory files.
		*/
		static FILE_STATUS ListDir( const WString& path , const WString& spec ,
			std::vector<WString>& files );

		/*!
			\brief		Create directory.
		*/
		static FILE_STATUS CreateDir( const WString& path );

		/*! 
			\brief	File data used in file enumeration.
		*/
		struct EnumFileData
		{
			/// \brief File status indicates file type.
			FILE_STATUS		status;
			/// \brief File size.
			size_t			size;
			/// \brief File creation time.
			DateTime		creation;
			/// \brief File last accessed time.
			DateTime		accessed;
			/// \brief File last modified time.
			DateTime		modified;
			/// \brief File name.
			const wchar_t *	name;
		};

		/*!
			\brief		Enumerate files in a directory.
		*/
		static FILE_STATUS EnumerateFiles( const WString& path , const WString& spec ,
			function<void(const EnumFileData&)> handler );

		//@}

	private:

		// Handle to file.
		void *			m_hFile;

		// IO status.
		volatile int	m_status;

		// Full file path.
		WString			m_path;
	};

} // namespace xeres
